package com.skilltrackedu.exception;

import com.skilltrackedu.exception.enums.CommonError;
import com.skilltrackedu.exception.exception.CommonException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author LENOVO
 * @version 1.0
 * @date 2025/3/20 下午2:09\
 * 全局异常处理器
 */
// 使用Log4j记录日志
@Slf4j
// 使用@RestControllerAdvice注解标识该类为全局异常处理类
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理自定义异常
     * 当抛出 XueChengPlusException 异常时，该方法会被调用。
     *
     * @param e 自定义异常对象
     * @return 返回包含错误信息的 RestErrorResponse 对象
     * @ExceptionHandler 注解用于定义处理特定类型异常的方法。
     * 在本例中，该注解指定当前方法 customException 将专门处理 XueChengPlusException 类型的异常。
     * 当系统捕获到此类异常时，会自动调用此方法进行处理。
     * @ResponseStatus 注解用于指定 HTTP 响应状态码。
     * 在本例中，当 customException 方法被调用时，HTTP 响应将返回 500 (INTERNAL_SERVER_ERROR) 状态码，
     * 表示服务器内部错误。这有助于客户端快速了解请求失败的原因。
     */
    @ExceptionHandler(CommonException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse customException(CommonException e) {

        // 记录异常
        log.error("系统异常{}", e.getMessage(), e);

        // 解析出异常信息
        String errMessage = e.getMessage();
        return new RestErrorResponse(errMessage);
    }

    /**
     * 处理系统异常
     * 当抛出 Exception 异常时，该方法会被调用。
     *
     * @param e 异常对象
     * @return 返回包含通用错误信息的 RestErrorResponse 对象
     * @ExceptionHandler 注解用于定义处理特定类型异常的方法。
     * 在本例中，该注解指定当前方法 exception 将专门处理 Exception 类型的异常。
     * 当系统捕获到此类异常时，会自动调用此方法进行处理。
     * @ResponseStatus 注解用于指定 HTTP 响应状态码。
     * 在本例中，当 exception 方法被调用时，HTTP 响应将返回 500 (INTERNAL_SERVER_ERROR) 状态码，
     * 表示服务器内部错误。这有助于客户端快速了解请求失败的原因。
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse ethodArgumentNotValidException(Exception e) {

        log.error("【系统异常】{}", e.getMessage(), e);

        return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());
    }

    /**
     * 处理MethodArgumentNotValidException异常（参数校验异常）
     *
     * @param e 触发的MethodArgumentNotValidException异常实例，包含参数校验失败信息
     * @return 封装错误信息的RestErrorResponse响应对象，包含所有校验失败的提示信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse ethodArgumentNotValidException(MethodArgumentNotValidException e) {
        // 解析并提取参数校验异常中的错误信息
        BindingResult bindingResult = e.getBindingResult();

        // 收集所有字段校验错误信息
        List<String> erros = new ArrayList<>();

        bindingResult.getFieldErrors().stream().forEach(error -> {
            erros.add(error.getDefaultMessage());
        });

        // 拼接错误信息为逗号分隔字符串
        String errorMessage = StringUtils.join(erros, ",");

        // 记录包含原始异常和详细错误信息的日志
        log.error("【系统异常】{}", e.getMessage(),errorMessage);

        return new RestErrorResponse(errorMessage);
    }


}
